function Preferences(opt_startPoint, opt_getDefaultBranch, opt_noUnicode)
{
    var startPoint = opt_startPoint || null;
 		var prefSvc = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefService);
    if (opt_getDefaultBranch)
    {
        this.prefs_ = prefSvc.getDefaultBranch(startPoint)
    }
    else
    {
        this.prefs_ = prefSvc.getBranch(startPoint)
    }
    this.prefs_.QueryInterface(Components.interfaces.nsIPrefBranchInternal);
    this.noUnicode_ = !(!opt_noUnicode)
}

Preferences.setterMap_ = { string: "setCharPref", "boolean": "setBoolPref", number: "setIntPref" };
Preferences.getterMap_ = {};
Preferences.getterMap_[Components.interfaces.nsIPrefBranch.PREF_STRING] = "getCharPref";
Preferences.getterMap_[Components.interfaces.nsIPrefBranch.PREF_BOOL] = "getBoolPref";
Preferences.getterMap_[Components.interfaces.nsIPrefBranch.PREF_INT] = "getIntPref";
Preferences.prototype.setPref = function(key, val)
{
    var datatype = typeof val;
    if (datatype == "number" && val % 1 != 0)
    {
        alert("Cannot store non-integer numbers in preferences.");
				return;
    }
    if (datatype == "string" && !this.noUnicode_)
    {
        return this.setUnicodePref(key, val);
    }
    var meth = Preferences.setterMap_[datatype];
    if (!meth)
    {
        alert("Pref datatype {" + datatype + "} not supported.");
				return;
    }
    return this.prefs_[meth](key, val);
};
Preferences.prototype.getPref = function(key, opt_default)
{
    var type = this.prefs_.getPrefType(key);
    if (type == Components.interfaces.nsIPrefBranch.PREF_INVALID)
    {
        return opt_default
    }
    if (type == Components.interfaces.nsIPrefBranch.PREF_STRING && !this.noUnicode_)
    {
        return this.getUnicodePref(key, opt_default)
    }
    var meth = Preferences.getterMap_[type];
    if (!meth)
    {
        alert("Pref datatype {" + type + "} not supported.");
				return;
    }
    try
    {
        return this.prefs_[meth](key)
    }
    catch (e)
    {
        return opt_default
    }
};
Preferences.prototype.setUnicodePref = function(key, value)
{
    var s = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString);
    s.data = value;
    return this.prefs_.setComplexValue(key, Components.interfaces.nsISupportsString, s)
};

Preferences.prototype.getUnicodePref = function(key, opt_default)
{
    try
    {
        return this.prefs_.getComplexValue(key, Components.interfaces.nsISupportsString).data
    }
    catch (e)
    {
        return opt_default
    }
};
Preferences.prototype.setBoolPref = function(which, value)
{
    return this.setPref(which, value)
};
Preferences.prototype.getBoolPref = function(which)
{
    return this.prefs_.getBoolPref(which)
};
Preferences.prototype.getBoolPrefOrDefault = function(which, def)
{
    return this.getPref(which, def)
};
Preferences.prototype.getBoolPrefOrDefaultAndSet = function(which, def)
{
    try
    {
        return this.prefs_.getBoolPref(which)
    }
    catch (e)
    {
        this.prefs_.setBoolPref(which, !(!def));
        return def
    }
};
Preferences.prototype.clearPref = function(which)
{
    try
    {
        this.prefs_.clearUserPref(which)
    }
    catch (e){}
};

Preferences.prototype.getChildNames = function(opt_startingPoint)
{
    if (!opt_startingPoint)
    {
        opt_startingPoint = ""
    }
    return this.prefs_.getChildList(opt_startingPoint, {}
    )
};
Preferences.prototype.savePrefFile = function()
{
    var prefService = Components.classes["@mozilla.org/preferences;1"].getService
        (Components.interfaces.nsIPrefService);
    try
    {
        prefService.savePrefFile(null)
    }
    catch (e){}
};